#if AudienceNetwork
using System;
using UnityEngine;
using AudienceNetwork;

public class AudienceNetworkController :MonoBehaviour, AdController
{
    public enum AdType
    {
        Test,
        Android,
        IOS,
    }

    AdType curAdType
    {
        get
        {
            if (Application.platform == RuntimePlatform.IPhonePlayer)
            {
                return AdType.IOS;
            }
            else if (Application.platform == RuntimePlatform.Android)
            {
                return AdType.Android;
            }
            else
            {
                GameDebug.LogError($"ad current unsupport platform:{Application.platform}");
                return AdType.Test;
            }
        }
    }
    
    string bannerAdUnitId
    {
        get
        {
            if (curAdType == AdType.Android)
                return "1157543734700080_1204563459998107";
            else if (curAdType == AdType.IOS)
                return "1157543734700080_1195814284206358";
            else
                return "";
        }
    }
    
    string interstitialAdUnitId
    {
        get
        {
            if (curAdType == AdType.Android)
                return "1157543734700080_1204562659998187";
            else if (curAdType == AdType.IOS)
                return "1157543734700080_1195814830872970";
            else
                return "";
        }
    }
    
    string rewardAdUnitId
    {
        get
        {
            if (curAdType == AdType.Android)
                return "1157543734700080_1204563153331471";
            else if (curAdType == AdType.IOS)
                return "1157543734700080_1195815030872950";
            else
                return "";
        }
    }

    /// <summary>
    /// Banner Ad
    /// </summary>
    private AdView m_BannerView;

    /// <summary>
    /// Interstitial Ad
    /// </summary>
    private InterstitialAd m_Interstitial;
    bool m_InterstitialLoaded;
    bool m_InterstitialClosed;

    /// <summary>
    /// Video Ad
    /// </summary>
    RewardedVideoAd m_RewardedAd;

    bool m_VideoLoaded;
    bool m_VideoClosed;
    bool m_VideoSuc;

    public void Init()
    {
        GameDebug.Log($"AudienceNetwork Init bannerAdUnitId :{this.bannerAdUnitId}  interstitialAdUnitId :{this.interstitialAdUnitId}  rewardAdUnitId :{this.rewardAdUnitId}");

        AudienceNetworkAds.Initialize();

        AudienceNetwork.AdSettings.AddTestDevice("807e73b2-4202-40c6-8b4b-993d8347e00f");
    }

    #region RewardAd

    public void LoadVideoAd()
    {
        Debug.Log("AudienceNetwork -> LoadVideoAd");

        m_VideoSuc = false;

        // Create the rewarded video unit with a placement ID (generate your own on the Facebook app settings).
        // Use different ID for each ad placement in your app.
        m_RewardedAd = new RewardedVideoAd(rewardAdUnitId);

        // For S2S validation you can create the rewarded video ad with the reward data
        // Refer to documentation here:
        // https://developers.facebook.com/docs/audience-network/android/rewarded-video#server-side-reward-validation
        // https://developers.facebook.com/docs/audience-network/ios/rewarded-video#server-side-reward-validation
        RewardData rewardData = new RewardData
        {
            UserId = "USER_ID",
            Currency = "REWARD_ID"
        };

        m_RewardedAd.Register(gameObject);

        // Set delegates to get notified on changes or when the user interacts with the ad.
        m_RewardedAd.RewardedVideoAdDidLoad = HandleRewardedAdLoaded;

        m_RewardedAd.RewardedVideoAdDidFailWithError = HandleRewardedAdFailedToLoad;

        m_RewardedAd.RewardedVideoAdWillLogImpression = delegate ()
        {
            Debug.Log("RewardedVideo ad logged impression.");
            HandleUserEarnedReward();//
        };
        m_RewardedAd.RewardedVideoAdDidClick = HandleRewardedAdOpening;

        // For S2S validation you need to register the following two callback
        // Refer to documentation here:
        // https://developers.facebook.com/docs/audience-network/android/rewarded-video#server-side-reward-validation
        // https://developers.facebook.com/docs/audience-network/ios/rewarded-video#server-side-reward-validation
        m_RewardedAd.RewardedVideoAdDidSucceed = HandleUserEarnedReward;

        m_RewardedAd.RewardedVideoAdDidFail = HandleRewardedAdFailedToShow;

        m_RewardedAd.RewardedVideoAdDidClose = HandleRewardedAdClosed;

#if UNITY_ANDROID
        /*
         * Only relevant to Android.
         * This callback will only be triggered if the Rewarded Video activity
         * has been destroyed without being properly closed. This can happen if
         * an app with launchMode:singleTask (such as a Unity game) goes to
         * background and is then relaunched by tapping the icon.
         */
        m_RewardedAd.RewardedVideoAdActivityDestroyed = delegate ()
        {
            if (!m_VideoClosed)
            {
                Debug.Log("Rewarded video activity destroyed without being closed first.");
                Debug.Log("Game should resume. User should not get a reward.");
            }
        };
#endif

        // Initiate the request to load the ad.
        m_RewardedAd.LoadAd(); 
    }

    public void PlayVideoAd()
    {
        Debug.Log("AudienceNetwork -> PlayerVideo");

        if (m_VideoLoaded)
        {
            m_VideoLoaded = false;
            m_RewardedAd.Show();
        } 
        else
        {
            GameDebug.LogError("Video ad has not ready");
            this.onVideoAdFailedToShow?.Invoke("Video ad has not ready, please try again later.");
        }

    }

    public void HandleRewardedAdLoaded()
    {
        Debug.Log("RewardedVideo ad loaded.");
        m_VideoLoaded = true;
        m_VideoClosed = false;
        string isAdValid = m_RewardedAd.IsValid() ? "valid" : "invalid";

        this.onVideoAdLoaded?.Invoke("");
    }

    public void HandleRewardedAdFailedToLoad(string error)
    {
        Debug.Log("RewardedVideo ad failed to load with error: " + error);

        this.onVideoAdFailedToLoad?.Invoke(error);
    }

    public void HandleRewardedAdOpening()
    {
        Debug.Log("RewardedVideo ad clicked.");

        this.onVideoAdOpening?.Invoke();
    }

    public void HandleRewardedAdFailedToShow()
    {
        Debug.Log("Rewarded video ad not validated, or no response from server");

        this.onVideoAdFailedToShow?.Invoke("");

        LoadVideoAd();
    }

    public void HandleRewardedAdClosed()
    {
        Debug.Log($"Rewarded video ad did close  m_VideoSuc:{m_VideoSuc}");
        if (m_VideoSuc) return;

        m_VideoClosed = true;
        if (m_RewardedAd != null)
        {
            m_RewardedAd.Dispose();
        }

        this.onVideoAdClosed?.Invoke();

        LoadVideoAd();
    }

    public void HandleUserEarnedReward()
    {
        Debug.Log("Rewarded video HandleUserEarnedReward.");
         m_VideoSuc = true;
        this.onVideoPlaySuc?.Invoke($"");
    }

    #endregion

    #region Interstitial



    public void LoadInterstitialAd()
    {
        Debug.Log("AudienceNetwork -> LoadInterstitialAd");

        // Create the interstitial unit with a placement ID (generate your own on the Facebook app settings).
        // Use different ID for each ad placement in your app.
        m_Interstitial = new InterstitialAd(interstitialAdUnitId);

        m_Interstitial.Register(gameObject);

        // Set delegates to get notified on changes or when the user interacts with the ad.
        m_Interstitial.InterstitialAdDidLoad = HandleOnInterstitialAdLoaded;

        m_Interstitial.InterstitialAdDidFailWithError = HandleOnInterstitialAdFailedToLoad;

        m_Interstitial.InterstitialAdWillLogImpression = delegate ()
        {
            Debug.Log("Interstitial ad logged impression.");
        };
        m_Interstitial.InterstitialAdDidClick = HandleOnInterstitialAdOpened;

        m_Interstitial.InterstitialAdDidClose = HandleOnInterstitialAdClosed;

#if UNITY_ANDROID
        /*
         * Only relevant to Android.
         * This callback will only be triggered if the Interstitial activity has
         * been destroyed without being properly closed. This can happen if an
         * app with launchMode:singleTask (such as a Unity game) goes to
         * background and is then relaunched by tapping the icon.
         */
        m_Interstitial.interstitialAdActivityDestroyed = delegate () {
            if (!m_InterstitialClosed)
            {
                Debug.Log("Interstitial activity destroyed without being closed first.");
                Debug.Log("Game should resume.");
            }
        };
#endif

        // Initiate the request to load the ad.
        m_Interstitial.LoadAd();
    }
    
    public void ShowInterstitialAd()
    {
        Debug.Log("Admod -> ShowInterstitialAd");

        if (m_InterstitialLoaded)
        {
            m_InterstitialLoaded = false;
            m_Interstitial.Show();
        }
        else
        {
            GameDebug.LogError("Interstitial has not ready");
        }
    }
    public void HandleOnInterstitialAdLoaded()
    {
        Debug.Log("Interstitial ad loaded.");

        m_InterstitialLoaded = true;
        m_InterstitialClosed = false;

        this.onInterstitialAdLoaded?.Invoke("");
    }

    public void HandleOnInterstitialAdFailedToLoad(string error)
    {
        Debug.Log("Interstitial ad failed to load with error: " + error);

        this.onInterstitialAdFailedToLoad?.Invoke(error);
    }

    public void HandleOnInterstitialAdOpened()
    {
        Debug.Log("Interstitial ad clicked.");

        this.onInterstitialAdOpening?.Invoke("");
    }

    public void HandleOnInterstitialAdClosed()
    {
        Debug.Log("Interstitial ad did close.");
        m_InterstitialClosed = true;

        if (m_Interstitial != null)
        {
            m_Interstitial.Dispose();
        }

        this.onInterstitialAdClosed?.Invoke("");
    }

    //public void HandleOnInterstitialAdLeavingApplication(object sender, EventArgs args)
    //{
    //    MonoBehaviour.print("Admod HandleAdLeavingApplication event received");

    //    this.onInterstitialAdLeavingApplication?.Invoke("");
    //}
    #endregion

    #region Banner
    private AdSize[] adSizeArray = (AdSize[])Enum.GetValues(typeof(AdSize));
    private ScreenOrientation currentScreenOrientation;

    public void LoadBanner()
    {
        
    }
    public void ShowBanner()
    {
        Debug.Log("Admod -> ShowBanner");

        if (m_BannerView)
        {
            m_BannerView.Dispose();
        }

        // Create a banner's ad view with a unique placement ID
        // (generate your own on the Facebook app settings).
        // Use different ID for each ad placement in your app.
        m_BannerView = new AdView(bannerAdUnitId, AdSize.BANNER_HEIGHT_50/*adSizeArray[currentAdSize]*/);
       
        m_BannerView.Register(gameObject);
        //currentAdViewPosition = AdPosition.BOTTOM;

        // Set delegates to get notified on changes or when the user interacts
        // with the ad.
        m_BannerView.AdViewDidLoad = HandleOnBannerAdLoaded;

        m_BannerView.AdViewDidFailWithError = HandleOnBannerAdFailedToLoad;

        m_BannerView.AdViewWillLogImpression = delegate ()
        {
            Debug.Log("Banner logged impression.");
        };
        m_BannerView.AdViewDidClick = HandleOnBannerAdOpened;

        // Initiate a request to load an ad.
        m_BannerView.LoadAd();
    }

    public void HideBanner()
    {
        Debug.Log("Admod -> HideBanner");
        
        if(m_BannerView != null)
            m_BannerView.Dispose();
        
        m_BannerView = null;
    }

    public void HandleOnBannerAdLoaded()
    {
        currentScreenOrientation = Screen.orientation;
        //m_BannerView.Show(100);
        string isAdValid = m_BannerView.IsValid() ? "valid" : "invalid";
        Debug.Log("Banner loaded");

        m_BannerView.Show(AdPosition.BOTTOM);

        this.onBannerAdLoaded?.Invoke("");
    }

    public void HandleOnBannerAdFailedToLoad(string error)
    {
        Debug.Log("Banner failed to load with error: " + error);

        this.onBannerAdFailedToLoad?.Invoke(error);
    }

    public void HandleOnBannerAdOpened()
    {
        Debug.Log("Banner clicked.");

        this.onBannerAdOpening?.Invoke("");
    }

    //public void HandleOnBannerAdClosed(object sender, EventArgs args)
    //{
    //    MonoBehaviour.print("Admod HandleAdClosed event received");

    //    this.onBannerAdClosed?.Invoke("");
    //}

    //public void HandleOnBannerAdLeavingApplication(object sender, EventArgs args)
    //{
    //    MonoBehaviour.print("Admod HandleAdLeavingApplication event received");

    //    this.onBannerAdLeavingApplication?.Invoke("");
    //}

    #endregion


    public void Release()
    {
        if (m_RewardedAd != null)
        { 
            //this.m_RewardedAd.OnAdLoaded -= HandleRewardedAdLoaded;
            //this.m_RewardedAd.OnAdFailedToLoad -= HandleRewardedAdFailedToLoad;
            //this.m_RewardedAd.OnAdOpening -= HandleRewardedAdOpening;
            //this.m_RewardedAd.OnAdFailedToShow -= HandleRewardedAdFailedToShow;
            //this.m_RewardedAd.OnUserEarnedReward -= HandleUserEarnedReward;
            //this.m_RewardedAd.OnAdClosed -= HandleRewardedAdClosed;
            m_RewardedAd = null;
        }

        if (this.m_Interstitial != null)
        {
            //this.m_Interstitial.OnAdLoaded -= HandleOnInterstitialAdLoaded;
            //this.m_Interstitial.OnAdFailedToLoad -= HandleOnInterstitialAdFailedToLoad;
            //this.m_Interstitial.OnAdOpening -= HandleOnInterstitialAdOpened;
            //this.m_Interstitial.OnAdClosed -= HandleOnInterstitialAdClosed;
            //this.m_Interstitial.OnAdLeavingApplication -= HandleOnInterstitialAdLeavingApplication;
            m_Interstitial = null;
        }

        if (this.m_BannerView != null)
        {
            //this.m_BannerView.OnAdLoaded -= this.HandleOnBannerAdLoaded;
            //this.m_BannerView.OnAdFailedToLoad -= this.HandleOnBannerAdFailedToLoad;
            //this.m_BannerView.OnAdOpening -= this.HandleOnBannerAdOpened;
            //this.m_BannerView.OnAdClosed -= this.HandleOnBannerAdClosed;
            //this.m_BannerView.OnAdLeavingApplication -= this.HandleOnBannerAdLeavingApplication;
            m_BannerView = null;
        }

        HideBanner();
    }

    public void ReleaseBannerEvent()
    {
        onBannerAdLoaded = null;
        onBannerAdFailedToLoad  = null;
        onBannerAdOpening = null;
        onBannerAdClosed  = null;
        onBannerAdLeavingApplication  = null;

        m_BannerView = null;
    }

    public void ReleaseInterstitialEvent()
    {
        onInterstitialAdLoaded = null;
        onInterstitialAdFailedToLoad = null;
        onInterstitialAdOpening = null;
        onInterstitialAdClosed = null;
        onInterstitialAdLeavingApplication = null;

        m_Interstitial = null;
    }

    public void ReleaseVideoEvent()
    {
        onVideoAdLoaded  = null;
        onVideoAdFailedToLoad  = null;
        onVideoAdOpening   = null;
        onVideoAdFailedToShow  = null;
        onVideoPlaySuc  = null;
        onVideoAdClosed  = null;

        m_RewardedAd = null;
    }



    private Action<string> m_OnBannerAdLoaded;
    public Action<string>onBannerAdLoaded
    {
        get { return m_OnBannerAdLoaded;}
        set { m_OnBannerAdLoaded = value; }
    }

    // Called when an Banner ad request failed to load.
    public Action<string> m_OnBannerAdFailedToLoad; 
    public Action<string>onBannerAdFailedToLoad
    {
        get { return m_OnBannerAdFailedToLoad;}
        set { m_OnBannerAdFailedToLoad = value; }
    }

    public Action<string> onBannerShowSuc { get; set; }
    public Action<string> onBannerShowFailed { get; set; }

    // Called when an Banner ad is clicked.
    public Action<string> m_OnBannerAdOpening;
    public Action<string>onBannerAdOpening
    {
        get { return m_OnBannerAdOpening;}
        set { m_OnBannerAdOpening = value; }
    }
    // Called when the user returned from the app after an Banner ad click.
    public Action<string> m_OnBannerAdClosed;
    public Action<string>onBannerAdClosed
    {
        get { return m_OnBannerAdClosed;}
        set { m_OnBannerAdClosed = value; }
    }
    // Called when the Banner ad click caused the user to leave the application.
    public Action<string> m_OnBannerAdLeavingApplication;
    public Action<string>onBannerAdLeavingApplication
    {
        get { return m_OnBannerAdLeavingApplication;}
        set { m_OnBannerAdLeavingApplication = value; }
    }
	 
    // Called when an Interstitial ad request has successfully loaded.
    public Action<string> m_OnInterstitialAdLoaded;
    public Action<string>onInterstitialAdLoaded
    {
        get { return m_OnInterstitialAdLoaded;}
        set { m_OnInterstitialAdLoaded = value; }
    }
    // Called when an Interstitial ad request failed to load.
    public Action<string> m_OnInterstitialAdFailedToLoad;
    public Action<string>onInterstitialAdFailedToLoad
    {
        get { return m_OnInterstitialAdFailedToLoad;}
        set { m_OnInterstitialAdFailedToLoad = value; }
    }

    public Action<string> onInterstitialAdSuc { get; set; }
    public Action<string> onInterstitialAdFail { get; set; }

    // Called when an Interstitial ad is shown.
    public Action<string> m_OnInterstitialAdOpening;
    public Action<string>onInterstitialAdOpening
    {
        get { return m_OnInterstitialAdOpening;}
        set { m_OnInterstitialAdOpening = value; }
    }
    // Called when the Interstitial ad is closed.
    public Action<string> m_OnInterstitialAdClosed;
    public Action<string>onInterstitialAdClosed
    {
        get { return m_OnInterstitialAdClosed;}
        set { m_OnInterstitialAdClosed = value; }
    }
    // Called when the Interstitial ad click caused the user to leave the application.
    public Action<string> m_OnInterstitialAdLeavingApplication;
    public Action<string>onInterstitialAdLeavingApplication
    {
        get { return m_OnInterstitialAdLeavingApplication;}
        set { m_OnInterstitialAdLeavingApplication = value; }
    }

    public Action<string> m_OnVideoAdLoaded;
    public Action<string>onVideoAdLoaded
    {
        get { return m_OnVideoAdLoaded;}
        set { m_OnVideoAdLoaded = value; }
    }
    // Called when an ad request failed to load.
    public Action<string> m_OnVideoAdFailedToLoad;
    public Action<string>onVideoAdFailedToLoad
    {
        get { return m_OnVideoAdFailedToLoad;}
        set { m_OnVideoAdFailedToLoad = value; }
    }
    // Called when an ad is shown.
    public Action m_OnVideoAdOpening;
    public Action onVideoAdOpening
    {
        get { return m_OnVideoAdOpening;}
        set { m_OnVideoAdOpening = value; }
    }
    // Called when an ad request failed to show.
    public Action<string> m_OnVideoAdFailedToShow;
    public Action<string>onVideoAdFailedToShow
    {
        get { return m_OnVideoAdFailedToShow;}
        set { m_OnVideoAdFailedToShow = value; }
    }
    // Called when the user should be rewarded for interacting with the ad.
    public Action<string> m_OnVideoUserEarnedReward;
    public Action<string>onVideoPlaySuc
    {
        get { return m_OnVideoUserEarnedReward;}
        set { m_OnVideoUserEarnedReward = value; }
    }
    // Called when the ad is closed.
    public Action  m_OnVideoAdClosed;
    public Action onVideoAdClosed
    {
        get { return m_OnVideoAdClosed;}
        set { m_OnVideoAdClosed = value; }
    }

    public bool IsVideoReady => m_RewardedAd !=null && m_VideoLoaded;
    public bool IsInterstitialReady => m_Interstitial !=null && m_InterstitialLoaded;

}

#endif